﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using Microsoft.Xna.Framework;
using System.Xml;
using System.Xml.Serialization;
using System.Runtime.Serialization;
using System.Runtime.Serialization.Formatters.Binary;
using System.IO;

namespace Particle_Editor
{
    public  partial class ControlWindow : Form
    {
        string ImageFilter;
        public ControlWindow()
        {
            InitializeComponent();
        }
        public IntPtr getDrawSurface()
        {
            return Surface.Handle;
        }

        private void ControlWindow_FormClosed(object sender, FormClosedEventArgs e)
        {
            Application.Exit();
        }
     
        private void button1_Click(object sender, EventArgs e)
        {
           
        }

        private void UpdateTimer_Tick(object sender, EventArgs e)
        {
            CurrentFPS.Text = "FPS: " + Game1.CurrentFPS.ToString();
            LBParticlesCreated.Text = "Particles Created: " + Game1.TotalParticlesCreated.ToString();
            LBParticlesDestroyed.Text = "Particles Destroyed: " + Game1.TotalParticlesDestroyed.ToString();
            LBTimeElapsed.Text = "Elapsed Time: " + Game1.TimeElapsedSinceStart.ToString();
            LBEmitterLocation.Text = "Emitter Position (X: " +Game1.EmitterLocation.X + ", Y: " + Game1.EmitterLocation.Y + ")";
        }

        private void button1_Click_1(object sender, EventArgs e)
        {
            ApplyChanges();
        }

        private void BColor_Click(object sender, EventArgs e)
        {
            DLGColor.ShowDialog();
            NUPColorR.Value = DLGColor.Color.R;
            NUPColorG.Value = DLGColor.Color.G;
            NUPColorB.Value = DLGColor.Color.B;
            BColor.BackColor = DLGColor.Color;
            
        }

        private void NUPColorR_ValueChanged(object sender, EventArgs e)
        {
            BColor.BackColor = Color.FromArgb(255, DLGColor.Color.R, DLGColor.Color.G, DLGColor.Color.B);
        }

        private void NUPColorG_ValueChanged(object sender, EventArgs e)
        {
            BColor.BackColor = Color.FromArgb(255, DLGColor.Color.R, DLGColor.Color.G, DLGColor.Color.B);
        }

        private void NUPColorB_ValueChanged(object sender, EventArgs e)
        {
            BColor.BackColor = Color.FromArgb(255, DLGColor.Color.R, DLGColor.Color.G, DLGColor.Color.B);
        }

        private void CBEffect_SelectedIndexChanged(object sender, EventArgs e)
        {
            //1 Explosion
            //2 Fire
            //3 Smoke
            //4 User Defined
            switch (CBEffect.SelectedItem.ToString())
            {
                case "User Defined":
                    {
                    }
                    break;
                case "Fire":
                    {

                        //Default fire effect setup
                        NUPMinParticleCount.Value = 50;
                        NUPMaxParticleCount.Value = 250;
                        NUPMinAccel.Value = 2;
                        NUPMaxAccel.Value = 5;
                        NUPMinSpeed.Value = 10;
                        NUPMaxSpeed.Value = 120;
                        NUPMinLifetime.Value = 5;
                        NUPMaxLifetime.Value = 7;
                        NUPMinRotationSpeed.Value = (decimal)0.2f;
                        NUPMaxRotationSpeed.Value = (decimal)0.2f;
                        NUPMinAngle.Value = 0;
                        NUPMaxAngle.Value = 180;
                        NUPMinScale.Value = (decimal)0.2f;
                        NUPMaxScale.Value = (decimal)0.8f;
                        NUPColorR.Value = 255;
                        NUPColorG.Value = 255;
                        NUPColorB.Value = 255;
                        BColor.BackColor = Color.White;
                        LBParticleTextures.SelectedItem = "Fire";
                        Game1.CurrentParticleTexture = "Fire";

                        
                    }
                    break;
                case "Smoke":
                    {
                        NUPMinParticleCount.Value = 100;
                        NUPMaxParticleCount.Value = 300;
                        NUPMinAccel.Value = 2;
                        NUPMaxAccel.Value = 5;
                        NUPMinSpeed.Value = 10;
                        NUPMaxSpeed.Value = 120;
                        NUPMinLifetime.Value = 5;
                        NUPMaxLifetime.Value = 7;
                        NUPMinRotationSpeed.Value = (decimal)0.1f;
                        NUPMaxRotationSpeed.Value = (decimal)0.1f;
                        NUPMinAngle.Value = 0;
                        NUPMaxAngle.Value = 180;
                        NUPMinScale.Value = (decimal)0.5f;
                        NUPMaxScale.Value = (decimal)1.0f;
                        NUPColorR.Value = 255;
                        NUPColorG.Value = 255;
                        NUPColorB.Value = 255;
                        BColor.BackColor = Color.White;
                        LBParticleTextures.SelectedItem = "Smoke";
                        Game1.CurrentParticleTexture = "Smoke";
                    }
                    break;
                case "Explosion":
                    {
                        //Default explosion effect
                        NUPMinParticleCount.Value = 150;
                        NUPMaxParticleCount.Value = 250;
                        NUPMinAccel.Value = 2;
                        NUPMaxAccel.Value = 5;
                        NUPMinSpeed.Value = 100;
                        NUPMaxSpeed.Value = 160;
                        NUPMinLifetime.Value = 5;
                        NUPMaxLifetime.Value = 7;
                        NUPMinRotationSpeed.Value = (decimal)0.2f;
                        NUPMaxRotationSpeed.Value = (decimal)0.2f;
                        NUPMinAngle.Value = 0;
                        NUPMaxAngle.Value = 360;
                        NUPMinScale.Value = (decimal)0.2f;
                        NUPMaxScale.Value = (decimal)0.8f;
                        NUPColorR.Value = 255;
                        NUPColorG.Value = 255;
                        NUPColorB.Value = 255;
                        BColor.BackColor = Color.White;
                        LBParticleTextures.SelectedItem = "Fire";
                        NUPEmitterSpawnRate.Value = 5;
                        Game1.CurrentParticleTexture = "Fire";
                    }
                    break;
            }
        }

        private void ControlWindow_Load(object sender, EventArgs e)
        {
            ImageFilter = "Image Files (JPEG, GIF, BMP,    etc.)|" +    
                             "*.jpg;*.jpeg;*.gif;*.bmp;*.tif;*.tiff;*.png|" +  
                             "JPEG files (*.jpg;*.jpeg)|*.jpg;*.jpeg|" + 
                             "GIF Files (*.gif)|*.gif|" + 
                             "BMP Files (*.bmp)|*.bmp|" + 
                             "TIFF Files (*.tif;*.tiff)|*.tif;*.tiff|" + 
                             "PNG Files (*.png)|*.png|" + 
                             "All files (*.*)|*.*";
             OFD.Filter = ImageFilter;
             ResetAllValues();

        }

        private void button2_Click(object sender, EventArgs e)
        {
            if (OFD.ShowDialog() == DialogResult.OK)
            {
                string CurrentParticleTexture = OFD.FileName;
                try
                {
                    Game1.UsingExternalTexture = true;
                    Game1.ExternalTextureFileName = CurrentParticleTexture;
                    Game1.ResetParticles = true;
                    TBLoadedTexture.Text = CurrentParticleTexture;

                }
                catch(Exception theException)
                {
                    string message = theException.Message;
                    MessageBox.Show("Unable to load the specified texture. Error message: " + message, "Error Loading Texture", MessageBoxButtons.OK, MessageBoxIcon.Error);
                    Game1.UsingExternalTexture = false;
                    Game1.CurrentParticleTexture = "NoTexture";
                }
            }
        }

        private void LBParticleTextures_SelectedIndexChanged(object sender, EventArgs e)
        {
            Game1.UsingExternalTexture = false;
        }


        void ResetAllValues()
        {
            NUPMinSpeed.Value = 10;
            NUPMaxSpeed.Value = 100;
            NUPMinAccel.Value = 0;
            NUPMaxAccel.Value = 0;
            NUPMinLifetime.Value = 5;
            NUPMaxLifetime.Value = 7;
            NUPMinParticleCount.Value = 50;
            NUPMaxParticleCount.Value = 150;
            NUPMinRotationSpeed.Value = 1;
            NUPMaxRotationSpeed.Value = 5;
            NUPMinAngle.Value = 0;
            NUPMaxAngle.Value = 180;
            NUPMinScale.Value = (decimal)0.5f;
            NUPMaxScale.Value = 1;
            NUPColorR.Value = 255;
            NUPColorG.Value = 255;
            NUPColorB.Value = 255;
            BColor.BackColor = Color.White;
            NUPEmitterSpawnRate.Value = (decimal)0.2f;
            LBParticleTextures.SelectedItem = "NoTexture";
            CBEffect.SelectedItem = "User Defined";
            TBLoadedTexture.Clear();
            
        }

        private void toolStripButton5_Click(object sender, EventArgs e)
        {
            ResetAllValues();
        }

        private void toolStripButton1_Click(object sender, EventArgs e)
        {
            ResetAllValues();
        }

        private void newToolStripMenuItem_Click(object sender, EventArgs e)
        {
            ResetAllValues();
           
        }
  
        void SaveParticleSystem(string FileName)
        {
            InfoSaver theInfo = new InfoSaver();
            theInfo.MinParticleSpeed = (float)NUPMinSpeed.Value; 
            theInfo.MaxParticleSpeed = (float)NUPMaxSpeed.Value;
            theInfo.MinParticleAcceleration = (float)NUPMinAccel.Value;
            theInfo.MaxParticleAcceleration = (float)NUPMaxAccel.Value;
            theInfo.MinParticleLifetime = (float)NUPMinLifetime.Value;
            theInfo.MaxParticleLifetime = (float)NUPMaxLifetime.Value;
            theInfo.MinNumberOfParticles = (int)NUPMinParticleCount.Value;
            theInfo.MaxNumberOfParticles = (int)NUPMaxParticleCount.Value;
            theInfo.MinParticleRotationSpeed = (float)NUPMinRotationSpeed.Value;
            theInfo.MaxParticleRotationSpeed = (float)NUPMaxRotationSpeed.Value;
            theInfo.MinimumParticleAngle = (float)NUPMinAngle.Value;
            theInfo.MaximumParticleAngle = (float)NUPMaxAngle.Value;
            theInfo.MinParticleScale = (float)NUPMinScale.Value;
            theInfo.MaxParticleScale = (float)NUPMaxScale.Value;
            theInfo.ParticleColorR = (int)NUPColorR.Value;
            theInfo.ParticleColorG = (int)NUPColorG.Value;
            theInfo.ParticleColorB = (int)NUPColorB.Value;
            theInfo.PickerColor = BColor.BackColor;
            theInfo.EmitterSpawnRate = (float)NUPEmitterSpawnRate.Value;

            if (Game1.UsingExternalTexture == false)
            {
                theInfo.CurrentParticleTexture = LBParticleTextures.SelectedItem.ToString();
                theInfo.CustomTexture = false;
            }
            else
            {
                theInfo.CurrentParticleTexture = TBLoadedTexture.Text;
                theInfo.CustomTexture = true;
            }

            XmlSerializer theSerializer = new XmlSerializer(typeof(InfoSaver));
            TextWriter theWriter = new StreamWriter(FileName);
            theSerializer.Serialize(theWriter, theInfo);
            theWriter.Close();
        }
        void ExportToBinary(string FileName)
        {
            Stream theWriter = new FileStream(FileName, System.IO.FileMode.Create);
            IFormatter formatter = new BinaryFormatter();

            InfoSaver theInfo = new InfoSaver();
            theInfo.MinParticleSpeed = (float)NUPMinSpeed.Value;
            theInfo.MaxParticleSpeed = (float)NUPMaxSpeed.Value;
            theInfo.MinParticleAcceleration = (float)NUPMinAccel.Value;
            theInfo.MaxParticleAcceleration = (float)NUPMaxAccel.Value;
            theInfo.MinParticleLifetime = (float)NUPMinLifetime.Value;
            theInfo.MaxParticleLifetime = (float)NUPMaxLifetime.Value;
            theInfo.MinNumberOfParticles = (int)NUPMinParticleCount.Value;
            theInfo.MaxNumberOfParticles = (int)NUPMaxParticleCount.Value;
            theInfo.MinParticleRotationSpeed = (float)NUPMinRotationSpeed.Value;
            theInfo.MaxParticleRotationSpeed = (float)NUPMaxRotationSpeed.Value;
            theInfo.MinimumParticleAngle = (float)NUPMinAngle.Value;
            theInfo.MaximumParticleAngle = (float)NUPMaxAngle.Value;
            theInfo.MinParticleScale = (float)NUPMinScale.Value;
            theInfo.MaxParticleScale = (float)NUPMaxScale.Value;
            theInfo.ParticleColorR = (int)NUPColorR.Value;
            theInfo.ParticleColorG = (int)NUPColorG.Value;
            theInfo.ParticleColorB = (int)NUPColorB.Value;
            theInfo.PickerColor = BColor.BackColor;
            theInfo.EmitterSpawnRate = (float)NUPEmitterSpawnRate.Value;

            if (Game1.UsingExternalTexture == false)
            {
                theInfo.CurrentParticleTexture = LBParticleTextures.SelectedItem.ToString();
                theInfo.CustomTexture = false;
            }
            else
            {
                theInfo.CurrentParticleTexture = TBLoadedTexture.Text;
                theInfo.CustomTexture = true;
            }

            formatter.Serialize(theWriter, theInfo);
            theWriter.Close();

        }
        void LoadParticleSystem(string theFile)
        {
            XmlSerializer theDeserializer = new XmlSerializer(typeof(InfoSaver));
            TextReader theReader = new StreamReader(theFile);
            InfoSaver theInfo;
            theInfo = (InfoSaver)theDeserializer.Deserialize(theReader);
            theReader.Close();

            NUPMinSpeed.Value = (decimal)theInfo.MinParticleSpeed;
            NUPMaxSpeed.Value = (decimal)theInfo.MaxParticleSpeed;
            NUPMinAccel.Value = (decimal)theInfo.MinParticleAcceleration;
            NUPMaxAccel.Value = (decimal)theInfo.MinParticleAcceleration;
            NUPMinLifetime.Value = (decimal)theInfo.MinParticleLifetime;
            NUPMaxLifetime.Value = (decimal)theInfo.MinParticleLifetime;
            NUPMinParticleCount.Value = (decimal)theInfo.MinNumberOfParticles;
            NUPMaxParticleCount.Value = (decimal)theInfo.MaxNumberOfParticles;
            NUPMinRotationSpeed.Value = (decimal)theInfo.MinParticleRotationSpeed;
            NUPMaxRotationSpeed.Value = (decimal)theInfo.MaxParticleRotationSpeed;
            NUPMinAngle.Value = (decimal)theInfo.MinimumParticleAngle;
            NUPMaxAngle.Value = (decimal)theInfo.MaximumParticleAngle;
            NUPMinScale.Value = (decimal)theInfo.MinParticleScale;
            NUPMaxScale.Value = (decimal)theInfo.MaxParticleScale;
            NUPColorR.Value = (decimal)theInfo.ParticleColorR;
            NUPColorG.Value = (decimal)theInfo.ParticleColorG;
            NUPColorB.Value = (decimal)theInfo.ParticleColorB;
            BColor.BackColor = Color.FromArgb(255, (int)NUPColorR.Value, (int)NUPColorG.Value, (int)NUPColorB.Value);
            NUPEmitterSpawnRate.Value = (decimal)theInfo.EmitterSpawnRate;

            if (theInfo.CustomTexture == true)
            {
                Game1.UsingExternalTexture = true;
                Game1.ExternalTextureFileName = theInfo.CurrentParticleTexture;
                TBLoadedTexture.Text = theInfo.CurrentParticleTexture;
            }
            else
            {
                Game1.UsingExternalTexture = false;
                Game1.CurrentParticleTexture = theInfo.CurrentParticleTexture;
                LBParticleTextures.SelectedItem = theInfo.CurrentParticleTexture;
            }
            
            CBEffect.SelectedItem = "User Defined";
          
            Game1.MinParticleSpeed = (float)NUPMinSpeed.Value;
            Game1.MaxParticleSpeed = (float)NUPMaxSpeed.Value;

            Game1.MinNumberOfParticles = (int)NUPMinParticleCount.Value;
            Game1.MaxNumberOfParticles = (int)NUPMaxParticleCount.Value;

            Game1.MinParticleAcceleration = (float)NUPMinAccel.Value;
            Game1.MaxParticleAcceleration = (float)NUPMaxAccel.Value;

            Game1.MinParticleScale = (float)NUPMinScale.Value;
            Game1.MaxParticleScale = (float)NUPMaxScale.Value;

            Game1.MinParticleLifetime = (float)NUPMinLifetime.Value;
            Game1.MaxParticleLifetime = (float)NUPMaxLifetime.Value;

            Game1.MinParticleRotationSpeed = (-1) * ((float)NUPMinRotationSpeed.Value);
            Game1.MaxParticleRotationSpeed = (float)NUPMaxRotationSpeed.Value;

            Game1.MinimumParticleAngle = (float)NUPMinAngle.Value;
            Game1.MaximumParticleAngle = (float)NUPMaxAngle.Value;

            Game1.ParticleColorR = (int)NUPColorR.Value;
            Game1.ParticleColorG = (int)NUPColorG.Value;
            Game1.ParticleColorB = (int)NUPColorB.Value;

            Game1.EmitterSpawnRate = (float)NUPEmitterSpawnRate.Value;
            BColor.BackColor = Color.FromArgb(255, (int)NUPColorR.Value, (int)NUPColorG.Value, (int)NUPColorB.Value);
            Game1.ResetParticles = true;
            
            Game1.TotalParticlesCreated = 0;
            Game1.TotalParticlesDestroyed = 0;
            Game1.TimeElapsedSinceStart = 0;
          

        }

        private void toolStripButton3_Click(object sender, EventArgs e)
        {
            SaveSystem();
        }

        void SaveSystem()
        {
            if (SFD.ShowDialog() == DialogResult.OK)
            {
                string fname = SFD.FileName;
                try
                {
                    SaveParticleSystem(fname);
                }
                catch (Exception theException)
                {
                    string message = theException.Message;
                    MessageBox.Show("Unable to save the particle system. Error message: " + message, "Error Loading Texture", MessageBoxButtons.OK, MessageBoxIcon.Error);

                }
            }
        }
        void ExportSystem()
        {
            if (SFDExport.ShowDialog() == DialogResult.OK)
            {
                string fname = SFDExport.FileName;
                try
                {
                    ExportToBinary(fname);
                }
                catch (Exception theException)
                {
                    string message = theException.Message;
                    MessageBox.Show("Unable to export the particle system. Error message: " + message, "Error Loading Texture", MessageBoxButtons.OK, MessageBoxIcon.Error);

                }
            }
        }
        void LoadSystem()
        {
            if (OFDSystemLoader.ShowDialog() == DialogResult.OK)
            {
                string fname = OFDSystemLoader.FileName;
                try
                {
                    LoadParticleSystem(fname);
                }
                catch (Exception theException)
                {
                    string message = theException.Message;
                    MessageBox.Show("Unable to load the particle system. Error message: " + message, "Error Loading Texture", MessageBoxButtons.OK, MessageBoxIcon.Error);

                }
            }
        }
        void ApplyChanges()
        {
            
            Game1.CurrentParticleTexture = LBParticleTextures.SelectedItem.ToString();
            Game1.MinParticleSpeed = (float)NUPMinSpeed.Value;
            Game1.MaxParticleSpeed = (float)NUPMaxSpeed.Value;

            Game1.MinNumberOfParticles = (int)NUPMinParticleCount.Value;
            Game1.MaxNumberOfParticles = (int)NUPMaxParticleCount.Value;

            Game1.MinParticleAcceleration = (float)NUPMinAccel.Value;
            Game1.MaxParticleAcceleration = (float)NUPMaxAccel.Value;

            Game1.MinParticleScale = (float)NUPMinScale.Value;
            Game1.MaxParticleScale = (float)NUPMaxScale.Value;

            Game1.MinParticleLifetime = (float)NUPMinLifetime.Value;
            Game1.MaxParticleLifetime = (float)NUPMaxLifetime.Value;

            Game1.MinParticleRotationSpeed = (float)NUPMinRotationSpeed.Value;
            Game1.MaxParticleRotationSpeed = (float)NUPMaxRotationSpeed.Value;

            Game1.MinimumParticleAngle = (float)NUPMinAngle.Value;
            Game1.MaximumParticleAngle = (float)NUPMaxAngle.Value;

            Game1.ParticleColorR = (int)NUPColorR.Value;
            Game1.ParticleColorG = (int)NUPColorG.Value;
            Game1.ParticleColorB = (int)NUPColorB.Value;

            Game1.EmitterSpawnRate = (float)NUPEmitterSpawnRate.Value;
            BColor.BackColor = Color.FromArgb(255, (int)NUPColorR.Value, (int)NUPColorG.Value, (int)NUPColorB.Value);
            Game1.ResetParticles = true;
            Game1.TotalParticlesCreated = 0;
            Game1.TotalParticlesDestroyed = 0;
            Game1.TimeElapsedSinceStart = 0;
        }

        private void saveToolStripMenuItem_Click(object sender, EventArgs e)
        {
            SaveSystem();
        }

        private void toolStripButton2_Click(object sender, EventArgs e)
        {
            LoadSystem();
        }

        private void openToolStripMenuItem_Click(object sender, EventArgs e)
        {
            LoadSystem();
        }

        private void exitToolStripMenuItem_Click(object sender, EventArgs e)
        {
            Application.Exit();
        }

        private void toolStripButton4_Click(object sender, EventArgs e)
        {
            ExportSystem();
        }

        private void exportToolStripMenuItem_Click(object sender, EventArgs e)
        {
            ExportSystem();
        }
        
    }

    [Serializable]
    public class InfoSaver
    {
        
        public float MinParticleSpeed;
        public float MaxParticleSpeed;

        public float MinParticleAcceleration;
        public float MaxParticleAcceleration;

        public float MinParticleLifetime;
        public float MaxParticleLifetime;
        
        public float MinParticleScale;
        public float MaxParticleScale;
        
        public int MinNumberOfParticles;
        public int MaxNumberOfParticles;
        
        public float MinParticleRotationSpeed;
        public float MaxParticleRotationSpeed;
        
        public int ParticleColorR;
        public int ParticleColorG;
        public int ParticleColorB;
        
        public float MinimumParticleAngle;
        public float MaximumParticleAngle;
        
        public string CurrentParticleTexture;
        public bool CustomTexture;
        public Color PickerColor;
        public float EmitterSpawnRate;
    }
}
